/**
* @file    screen_mipicmd.c
* @brief   mipi cmd function
*
* Copyright (c) 2017 Huawei Tech.Co.,Ltd
*
* @author    HiMobileCam Reference Develop Team
* @date      2017/12/12
* @version   1.0

*/
#include "screen_mipidsi.h"

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/ioctl.h>

#include "hi_hal_common.h"

#ifdef __cplusplus
#if __cplusplus
extern "C" {
#endif
#endif /* __cplusplus */

#if !defined(AMP_LINUX)
extern int  mipi_tx_module_init(void);
extern void  mipi_tx_module_exit(void);
#endif

#define MIPIDSI_DEV       ("/dev/hi_mipi_tx")
static HI_S32 g_MipiDsiFd = -1;

HI_S32 MIPIDSI_Init(HI_VOID)
{
    HI_S32 ret = HI_SUCCESS;
#if !defined(AMP_LINUX)
    ret = mipi_tx_module_init();
    if (ret != HI_SUCCESS) {
        MLOGE("init screen failed\n");
        return HI_HAL_EINTER;
    };
#else
    ret = HI_insmod(HI_APPFS_KOMOD_PATH"/hi_mipi_tx.ko",NULL);
    if(ret != HI_SUCCESS) {
        MLOGE("insmod hi_mipi_tx:failed\n");
        return HI_HAL_EINTER;
    }
#endif
    g_MipiDsiFd = open(MIPIDSI_DEV, O_RDWR);
    if (g_MipiDsiFd == HAL_FD_INITIALIZATION_VAL) {
        return HI_HAL_EINTER;
    }
    return ret;
}

HI_S32 MIPIDSI_SetDeviceConfig(const combo_dev_cfg_t* devCfg)
{
    HI_APPCOMM_CHECK_POINTER(devCfg, HI_HAL_EINVAL);
    HI_S32 ret = HI_SUCCESS;
    combo_dev_cfg_t comboDevCfg = {0};
    memcpy(&comboDevCfg, devCfg, sizeof(combo_dev_cfg_t));

    if (comboDevCfg.output_mode == OUTPUT_MODE_DSI_VIDEO) {
        comboDevCfg.sync_info.edpi_cmd_size = 0;
    } else if (comboDevCfg.output_mode == OUTPUT_MODE_DSI_CMD){
        comboDevCfg.sync_info.edpi_cmd_size = comboDevCfg.sync_info.vid_pkt_size;
    } else {
        MLOGE("invalid mipi output mode.[%d]\n",comboDevCfg.output_mode);
        return HI_HAL_EINTER;
    }

    ret = ioctl(g_MipiDsiFd, HI_MIPI_TX_SET_DEV_CFG, &comboDevCfg);
    if (ret != HI_SUCCESS) {
        MLOGE("HI_MIPI_TX_SET_DEV_CFG failed.\n");
        close(g_MipiDsiFd);
        return HI_HAL_EINTER ;
    }
    return ret;
}

HI_S32 MIPIDSI_EnableVideoDataTransport(HI_VOID)
{
    HI_S32 ret = HI_SUCCESS;
    ret = ioctl(g_MipiDsiFd, HI_MIPI_TX_ENABLE);
    if (ret != HI_SUCCESS) {
        MLOGE("MIPI_TX enable failed\n");
        close(g_MipiDsiFd);
        return HI_HAL_EINTER;
    }
    return ret;
}

HI_S32 MIPIDSI_DisableVideoDataTransport(HI_VOID)
{
    HI_S32 ret = HI_SUCCESS;
    ret = ioctl(g_MipiDsiFd, HI_MIPI_TX_DISABLE);
    if (ret != HI_SUCCESS) {
        MLOGE("MIPI_TX disable failed\n");
        close(g_MipiDsiFd);
        return HI_HAL_EINTER;
    }
    return ret;
}

HI_VOID MIPIDSI_Deinit(HI_VOID)
{
    if (g_MipiDsiFd != HAL_FD_INITIALIZATION_VAL) {
        close(g_MipiDsiFd);
    }
#if !defined(AMP_LINUX)
    mipi_tx_module_exit();
#else
    HI_rmmod(HI_APPFS_KOMOD_PATH"/hi_mipi_tx.ko");
#endif
}

HI_S32 MIPIDSI_GENERIC_ShortWriteOneParam(HI_U8 cmd)
{
    HI_S32 ret = HI_SUCCESS;
    HI_U16 cmdSize = 0;
    HI_U16 localVal = 0;

    localVal = (0x00ff & cmd);
    cmdSize = cmdSize | localVal;

    cmd_info_t setCmdInfo = {0};
    setCmdInfo.devno = 0;
    setCmdInfo.cmd_size = cmdSize;
    setCmdInfo.data_type = 0x13;
    setCmdInfo.cmd = NULL;

    ret = ioctl(g_MipiDsiFd, HI_MIPI_TX_SET_CMD, &setCmdInfo);
    if (ret != HI_SUCCESS) {
        MLOGE("err: MIPI_TX write one data: [reg: 0x%x ] failed,\n",cmd);
        return HI_HAL_EINTER;
    }
    return ret;
}

HI_S32 MIPIDSI_GENERIC_ShortWriteTwoParam(HI_U8 cmd, HI_U8 data)
{
    HI_S32 ret = HI_SUCCESS;
    HI_U16 cmdSize = 0;
    HI_U16 localVal = 0;

    localVal = (0x00ff & data);
    cmdSize = (localVal << 8) | (0xff & cmd);

    cmd_info_t setCmdInfo = {0};
    setCmdInfo.devno = 0;
    setCmdInfo.cmd_size = cmdSize;
    setCmdInfo.data_type = 0x23;
    setCmdInfo.cmd = NULL;

    ret = ioctl(g_MipiDsiFd, HI_MIPI_TX_SET_CMD, &setCmdInfo);
    if (ret != HI_SUCCESS) {
        MLOGE("err: MIPI_TX write two data: [reg: 0x%x, value: 0x%x ] failed,\n",cmd, data);
        return HI_HAL_EINTER;
    }
    return ret;
}

HI_S32 MIPIDSI_GENERIC_LongWrite(HI_U8 dataCnt, const HI_U8* data)
{
    HI_APPCOMM_CHECK_POINTER(data, HI_HAL_EINVAL);
    HI_S32 ret = HI_SUCCESS;

    cmd_info_t setCmdInfo = {0};
    setCmdInfo.devno = 0;
    setCmdInfo.cmd_size = dataCnt;
    setCmdInfo.data_type = 0x29;
    setCmdInfo.cmd = (HI_U8*)data;

    ret = ioctl(g_MipiDsiFd, HI_MIPI_TX_SET_CMD, &setCmdInfo);
    if (ret != HI_SUCCESS) {
        MLOGE("err: MIPI_TX write long packet failed,\n");
        return HI_HAL_EINTER;
    }
    return ret;
}

HI_S32 MIPIDSI_GENERIC_Read(HI_U8 cmd, HI_U8 dataCnt, HI_U8* data)
{
    HI_APPCOMM_CHECK_POINTER(data, HI_HAL_EINVAL);
    HI_S32 ret = HI_SUCCESS;

    cmd_info_t setCmdInfo = {0};
    setCmdInfo.devno      = 0;
    setCmdInfo.data_type  = 0x37;
    setCmdInfo.cmd_size   = dataCnt;
    setCmdInfo.cmd        = NULL;
    ret = ioctl(g_MipiDsiFd, HI_MIPI_TX_SET_CMD, &setCmdInfo);
    if (ret != HI_SUCCESS) {
        MLOGE("HI_MIPI_TX_SET_CMD fail.\n");
        return HI_HAL_EINTER;
    }

    get_cmd_info_t getCmdInfo = {0};
    getCmdInfo.data_param = cmd;
    getCmdInfo.data_type = 0x14;
    getCmdInfo.devno = 0;
    getCmdInfo.get_data = data;
    getCmdInfo.get_data_size = dataCnt;
    ret = ioctl(g_MipiDsiFd, HI_MIPI_TX_GET_CMD, &getCmdInfo);
    if (ret != HI_SUCCESS) {
        MLOGE("HI_MIPI_TX_GET_CMD fail.\n");
        return HI_HAL_EINTER;
    }
    return ret;
}


HI_S32 MIPIDSI_DCS_ShortWriteNoParam(HI_U8 cmd)
{
    HI_S32 ret = HI_SUCCESS;
    HI_U16 cmdSize = 0;
    HI_U16 localVal = 0;

    localVal = (0x00ff & cmd);
    cmdSize = cmdSize | localVal;

    cmd_info_t setCmdInfo = {0};
    setCmdInfo.devno = 0;
    setCmdInfo.cmd_size = cmdSize;
    setCmdInfo.data_type = 0x05;
    setCmdInfo.cmd = NULL;

    ret = ioctl(g_MipiDsiFd, HI_MIPI_TX_SET_CMD, &setCmdInfo);
    if (ret != HI_SUCCESS) {
        MLOGE("err: MIPI_TX write one data: [reg: 0x%x ] failed,\n",cmd);
        return HI_HAL_EINTER;
    }
    return ret;
}

HI_S32 MIPIDSI_DCS_ShortWriteOneParam(HI_U8 cmd, HI_U8 data)
{
    HI_S32 ret = HI_SUCCESS;
    HI_U16 cmdSize = 0;
    HI_U16 localVal = 0;

    localVal = (0x00ff & data);
    cmdSize = (localVal << 8) | (0xff & cmd);

    cmd_info_t setCmdInfo = {0};
    setCmdInfo.devno = 0;
    setCmdInfo.cmd_size = cmdSize;
    setCmdInfo.data_type = 0x15;
    setCmdInfo.cmd = NULL;

    ret = ioctl(g_MipiDsiFd, HI_MIPI_TX_SET_CMD, &setCmdInfo);
    if (ret != HI_SUCCESS) {
        MLOGE("err: MIPI_TX write two data: [reg: 0x%x, value: 0x%x ] failed,\n",cmd, data);
        return HI_HAL_EINTER;
    }
    return ret;
}

HI_S32 MIPIDSI_DCS_LongWrite(HI_U8 dataCnt, const HI_U8* data)
{
    HI_APPCOMM_CHECK_POINTER(data, HI_HAL_EINVAL);
    HI_S32 ret = HI_SUCCESS;

    cmd_info_t setCmdInfo = {0};
    setCmdInfo.devno = 0;
    setCmdInfo.cmd_size = dataCnt;
    setCmdInfo.data_type = 0x39;
    setCmdInfo.cmd = (HI_U8*)data;

    ret = ioctl(g_MipiDsiFd, HI_MIPI_TX_SET_CMD, &setCmdInfo);
    if (ret != HI_SUCCESS) {
        MLOGE("err: MIPI_TX write long packet failed,\n");
        return HI_HAL_EINTER;
    }
    return ret;
}

HI_S32 MIPIDSI_DCS_Read(HI_U8 cmd, HI_U8 dataCnt, HI_U8* data)
{
    HI_APPCOMM_CHECK_POINTER(data, HI_HAL_EINVAL);
    HI_S32 ret = HI_SUCCESS;

    cmd_info_t setCmdInfo = {0};
    setCmdInfo.devno      = 0;
    setCmdInfo.data_type  = 0x37;
    setCmdInfo.cmd_size   = dataCnt;
    setCmdInfo.cmd        = NULL;
    ret = ioctl(g_MipiDsiFd, HI_MIPI_TX_SET_CMD, &setCmdInfo);
    if (ret != HI_SUCCESS) {
        MLOGE("HI_MIPI_TX_SET_CMD fail.\n");
        return HI_HAL_EINTER;
    }

    get_cmd_info_t getCmdInfo = {0};
    getCmdInfo.data_param = cmd;
    getCmdInfo.data_type = 0x06;
    getCmdInfo.devno = 0;
    getCmdInfo.get_data = data;
    getCmdInfo.get_data_size = dataCnt;
    ret = ioctl(g_MipiDsiFd, HI_MIPI_TX_GET_CMD, &getCmdInfo);
    if (ret != HI_SUCCESS) {
        MLOGE("HI_MIPI_TX_GET_CMD fail.\n");
        return HI_HAL_EINTER;
    }
    return ret;
}

#ifdef __cplusplus
#if __cplusplus
}
#endif
#endif /* __cplusplus */

